自從學了Vue 的 v-model 才發現對原生的 input 行為其實不太了解,而且在 Vue 中的 v-model 幾乎都是用原生的狀態去做出來的,趁這個機會來比較兩者之間相同及不相同的地方。
在這個範例中,會把取到 input 的值,再放到 <p>
tag 顯示出來。
在原生中,要取到 input 裡面的值必須要先操作DOM拿到這個 input ,拿到 input.value
之後再賦值給 p.textContent
html:
<div class="name-content">
<label for="name" >name: </label>
<input type="text" name="name" value="" id="name">
<p></p>
</div>
javascript:
const input = document.querySelector("input[name=name]")
const text = document.querySelector(".name-content p")
input.addEventListener('input', function(e) {
text.textContent = input.value;
})
Vue 有一個專門處理各種輸入的 v-model,不只可以用在 <input>
也可以用在 <select>
跟 <textarea>
上。
首先先創一個響應式變數 inputValue 放一個空字串,然後再把這個變數綁在 input 的 v-model 身上,再把下面的 <p>
tag 裡面用插值的方式放置變數,就可以取到 input 上的值了。
javascript:
const inputValue = ref('')
template:
<div class="name-content">
<label for="name" >name: </label>
<input type="text" v-model="inputValue" name="name" id="name">
<p>{{ inputValue }}</p>
</div>
就是這麼輕鬆寫意,不過再把 v-model 拆解出來,其實是同時使用了 v-bind: value
以及 v-on: input
。
一樣先有響應式變數 inputValue ,但是在監聽 input 事件的時候再用 $event.target.value
賦值給 inputValue,這一段其實就很像剛剛原生做的事情,只是 v-model 把這些都包起來了。
template:
<div class="name-content">
<label for="name" >name: </label>
<input type="text" v-bind:value="inputValue" @input="inputValue = $event.target.value" name="name" id="name">
<p>{{ inputValue }}</p>
</div>
但是跟剛剛的比對就知道,原生的 input 是使用監聽 input 事件才能取到當下的值,v-model 的 source code 也是用監聽 input 的事件;然而不是所有 input 都是監聽 input 事件的,可能只有 <input type='text'>
、 <textarea>
是如此, input 的 type 這麼多,每個都有不同的使用方法,接下來就會介紹一些特別的 input type。
input[type=checkbox]
會嘗試用一個群組的 checkbox 來做同樣的綁定。
使用 change 去監聽。<input type="checkbox">
是一個可以打勾的框框通常會搭配 <label>
當作敘述。
而 checkbox 就不是使用 value 來取到值,他沒有值,只有打勾或沒打勾,所以可以用 checked 來得知現在 true / false。
這次要做的是有好幾組 checkbox ,可以複選,把這幾組 checkbox 的值放到一個陣列裡,再顯示到 <p>
裡面:
template:
<div class="service-content">
<label>service:</label>
<input
type="checkbox"
value="good-service"
id="good-service" />
<label for="good-service">very good</label>
<input
type="checkbox"
value="normal-service"
id="normal-service"/>
<label for="normal-service">normal</label>
<input
type="checkbox"
value="bad-service"
id="bad-service" />
<label for="bad-service">bad</label>
</div>
<p></p>
javascript:
const serviceArray = [];
const good = document.querySelector('#good-service')
const normal = document.querySelector('#normal-service')
const bad = document.querySelector('#bad-service')
const serviceText = document.querySelector('p')
// 監聽每個的change事件
good.addEventListener('change', function() {
if(good.checked) {
serviceArray.push(good.value);
} else {
const index = serviceArray.indexOf('good-service');
serviceArray.splice(index, 1);
}
serviceText.textContent = serviceArray;
})
normal.addEventListener('change', function() {
if(normal.checked) {
serviceArray.push(normal.value);
} else {
const index = serviceArray.indexOf('normal-service');
serviceArray.splice(index, 1);
}
serviceText.textContent = serviceArray;
})
bad.addEventListener('change', function() {
if(bad.checked) {
serviceArray.push(bad.value);
} else {
const index = serviceArray.indexOf('bad-service');
serviceArray.splice(index, 1);
}
serviceText.textContent = serviceArray;
})
這樣寫落落長,超複雜的拉> <
要注意的是這裡都是用 input.value
來放進去 serviceArray。(在v-model裡面value是很重要的)
codepen: https://codepen.io/Jadddxx/pen/ExLOJXd?editors=0010
最前面有講到 v-model 是用綁定 value 跟監聽事件來完成的,所以有 value 的就要 綁同一個 v-model
javascript:
注意給的是一個陣列
const serviceArray = ref([]);
template:
<div class="service-content each-content">
<label>service:</label>
<input
type="checkbox"
value="good-service"
id="good-service"
v-model="serviceArray" />
<label for="good-service">very good</label>
<input
type="checkbox"
value="normal-service"
id="normal-service"
v-model="serviceArray" />
<label for="normal-service">normal</label>
<input
type="checkbox"
value="bad-service"
id="bad-service"
v-model="serviceArray" />
<label for="bad-service">bad</label>
</div>
<p>{{ serviceArray }}</p>
而如果 serviceArray
給的是一個空字串的話,就等於全部的 value 都要共用一個 v-model ,所以會打勾一個變成全部都連動的,而這個 v-model 別無他法只能變成 true / false。
一不小心 checkbox 程式碼爆表,分成兩天講,明天繼續 radio, select囉!